//
//  ScenesAudioManagerInternal.cpp
//  ScenesPlayer
//
//  Created by Branch on 2016/11/1.
//  Copyright © 2016年 Scenes. All rights reserved.
//

#include "ScenesAudioManagerInternal.h"
#include "VrAudioMix.h"
#include "IAudioDecoder.h"
#include "IAudioDecoderFactory.h"
#include "ScenesAudioCodec.h"
#include "ScenesAudioUtils.h"
#include <unistd.h>
#include "utils/log.h"
#include <assert.h>
//#include <pthread.h>
//#include <stdlib.h>
//#include <unistd.h>

static void onScenesAudioDecode(uint8_t* data,uint32_t len,int64_t presentationTimeUs,
                                int streamIndex,void* userData){
    
    ((ScenesAudioManagerInternal*)userData)->onAudioDecode(data, len, presentationTimeUs, streamIndex, userData);
}

static VrAudioMix* createAudioCodecs(int indexCount, int samplerate, int channels, ScenesAudioCodecCallback callback, void* userdata, IAudioDecoderFactory* factory, std::vector<ScenesAudioCodec*>& codecs) {
    VrAudioMix* mix = new VrAudioMix();
    mix->initFormat(indexCount, 1.0f / float(samplerate) / (16.0f / 8.0f) / float(channels));
    
    for (int i = 0;i < indexCount;++i){
        ScenesAudioCodec* scenesAudioCodec = new ScenesAudioCodec();
        if (!scenesAudioCodec->openDecoder(factory, i, callback, userdata)) {
            delete mix;
            mix = NULL;
            break;
        }
        codecs.push_back(scenesAudioCodec);
    }
    return mix;
}



namespace  {
    

}

ScenesAudioManagerInternal::ScenesAudioManagerInternal()
: _audioDecoderFactory(NULL)
, _vrAudioMix(NULL)
, _sampleRate(0)
, _channelsPerFrame(0)
, _bitsPerChannel(0)
//, _maxFrameCount(10)
{
    
}


ScenesAudioManagerInternal::~ScenesAudioManagerInternal(){
    
}


bool ScenesAudioManagerInternal::openScenesAudioManager(IAudioDecoderFactory* audioDecoderFactory,int sampleRate,
                                                int channelsPerFrame,int bitsPerChannel){

    if (bitsPerChannel != 16 ||
        sampleRate == 0 ||
        channelsPerFrame == 0 ||
        audioDecoderFactory == NULL){
        //目前只支持16位宽度
        //LOGE("format error or IAudioDecoderFactory is NULL !");
        return false;
    }


    
    _audioDecoderFactory = audioDecoderFactory;
    _bitsPerChannel = bitsPerChannel;
    _sampleRate = sampleRate;
    _channelsPerFrame = channelsPerFrame;
    return true;
}

void ScenesAudioManagerInternal::shutdown(){
    


    for (std::vector<ScenesAudioCodec*>::iterator iter = _scenesAudioCodecs.begin();
         iter != _scenesAudioCodecs.end(); ++iter) {
        (*iter)->shutdown();
        delete (*iter);
    }
    
    if (_vrAudioMix) {
        delete _vrAudioMix;
        _vrAudioMix = NULL;
    }
    _scenesAudioCodecs.clear();
}

void ScenesAudioManagerInternal::clean(){
    if (_vrAudioMix) {
        _vrAudioMix->clean();
    }
    for (std::vector<ScenesAudioCodec*>::iterator iter = _scenesAudioCodecs.begin();
         iter != _scenesAudioCodecs.end(); ++iter) {
        (*iter)->clean();

    }
    
}

bool ScenesAudioManagerInternal::inputSampleData(uint8_t* buff, int buffLen, int64_t sampleTimeUs){
    bool ret = true;

//    if (_vrAudioMix && _vrAudioMix->getCacheCount() >= _maxFrameCount) {
//        usleep(5000);
//    }
    
    int start = 0;
    std::vector<int> streams = ScenesAudioUtils::getAudioBuffInfo(buff, buffLen,&start);

    int count = (int)streams.size();
    //count = 1;
    if(count > 0){
        
        if (_vrAudioMix == NULL)
            _vrAudioMix = createAudioCodecs(count, _sampleRate, _channelsPerFrame, onScenesAudioDecode, this, _audioDecoderFactory, _scenesAudioCodecs);
//        while (_scenesAudioCodecs[0]->getCacheSize() > 2) {
//            usleep(5000);
//        }
        if (_scenesAudioCodecs[0]->getCacheSize() > 2) {
            //LOGV("inputSampleData false sampleTimeUs:%lld false",sampleTimeUs);
            return false;
        }
        //LOGV("inputSampleData true sampleTimeUs:%lld buffLen:%d",sampleTimeUs,buffLen);
        //LOGV("child thread tid = %ld\n", pthread_self());
        int offset = start;
        for (int i = 0; i < count; ++i) {
            //LOGV("inputSampleData sampleTimeUs:%lld i:%d\n",sampleTimeUs,i);

            _scenesAudioCodecs[i]->inputBuff(buff + offset, streams[i], sampleTimeUs);

            

            
            offset += streams[i];
        }


    }else{
        if (_vrAudioMix == NULL)
            _vrAudioMix = createAudioCodecs(1, _sampleRate, _channelsPerFrame, onScenesAudioDecode, this, _audioDecoderFactory, _scenesAudioCodecs);
        //BranchLog.LogE("普通音频");
        //普通音频
        _scenesAudioCodecs[0]->inputBuff(buff, buffLen, sampleTimeUs);

    }
    return ret;
    
}





bool ScenesAudioManagerInternal::outputSampleData(int64_t* out_sampleTimeUs){
    if (!_vrAudioMix){
        return false;
    }
    
    bool ret = _vrAudioMix->outputSampleTimeUs(out_sampleTimeUs);

    
    return ret;
}

bool ScenesAudioManagerInternal::getMixAudioData(float in_angle,int64_t in_sampleTimeUs,
                     uint8_t** out_buff,uint32_t* out_buffLen){
    if (_vrAudioMix == NULL){
        return false;
    }
    _vrAudioMix->setAngle(in_angle);
    //LOGV("getMixAudioData:%lld",in_sampleTimeUs);
    return _vrAudioMix->getMixAudioData(in_sampleTimeUs, out_buff, out_buffLen);
}

//bool ScenesAudioManagerInternal::getFrontBuff(float in_angle,uint32_t in_readLen,
//                                     uint8_t** out_buff,uint32_t* out_buffLen){
//    if (_vrAudioMix == NULL){
//        return false;
//    }
//    
//    _vrAudioMix->setAngle(in_angle);
//    if(_vrAudioMix->getFrontData(in_readLen, out_buff, out_buffLen) > 0){
//        return true;
//    }
//    return false;
//    
//}
//
//bool ScenesAudioManagerInternal::popFrontBuff(uint32_t buffLen){
//    bool ret = false;
//    if (_vrAudioMix) {
//        if(_vrAudioMix->popData(buffLen)){
//            ret = true;
//        }
//    }
//    return ret;
//}

void ScenesAudioManagerInternal::onAudioDecode(uint8_t* data,uint32_t len,int64_t presentationTimeUs,
                   int streamIndex,void* userData){
    
    if (_vrAudioMix) {
        _vrAudioMix->inputBuff(data, len, streamIndex, presentationTimeUs);
    }
}

